﻿using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows;

namespace RevitForge.Services
{
    public class ScriptExecuteHandler : IExternalEventHandler
    {
        // 存储用户输入的代码的静态属性
        public static string UserCode { get; set; }
        private readonly ExternalCommandData _commandData;
        private readonly string _message;
        private readonly ElementSet _elements;

        public ScriptExecuteHandler(ExternalCommandData commandData, string message, ElementSet elements)
        {
            _commandData = commandData;
            _message = message;
            _elements = elements;
        }
        public void Execute(UIApplication uiApp)
        {
            try
            {
                // 配置编译选项
                CSharpCompilationOptions compilationOptions = new CSharpCompilationOptions(
                    OutputKind.DynamicallyLinkedLibrary,
                    optimizationLevel: OptimizationLevel.Release,
                    allowUnsafe: true);

                // 解析源代码
                SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(UserCode);

                // 添加必要的程序集引用
                List<MetadataReference> references = new List<MetadataReference>
                {
                    MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                    MetadataReference.CreateFromFile(typeof(UIApplication).Assembly.Location),
                    MetadataReference.CreateFromFile(typeof(Document).Assembly.Location),
                    MetadataReference.CreateFromFile(typeof(System.Windows.MessageBox).Assembly.Location),
                    MetadataReference.CreateFromFile(Assembly.GetExecutingAssembly().Location),
                    MetadataReference.CreateFromFile(typeof(System.Linq.Enumerable).Assembly.Location)
                };

                // 创建编译
                string assemblyName = $"DynamicCommand_{DateTime.Now:yyyyMMddHHmmss}";
                CSharpCompilation compilation = CSharpCompilation.Create(
                    assemblyName,
                    new[] { syntaxTree },
                    references,
                    compilationOptions);

                // 在内存中编译
                using (var ms = new MemoryStream())
                {
                    Microsoft.CodeAnalysis.Emit.EmitResult result = compilation.Emit(ms);

                    if (!result.Success)
                    {
                        // 处理编译错误
                        IEnumerable<Diagnostic> failures = result.Diagnostics
                            .Where(diagnostic =>
                                diagnostic.IsWarningAsError ||
                                diagnostic.Severity == DiagnosticSeverity.Error);

                        string errorMessage = string.Join("\n", failures.Select(x => x.GetMessage()));
                        MessageBox.Show($"编译错误:\n{errorMessage}");
                        return;
                    }

                    // 加载编译后的程序集
                    ms.Seek(0, SeekOrigin.Begin);
                    Assembly assembly = Assembly.Load(ms.ToArray());

                    // 查找并执行命令
                    Type type = assembly.GetTypes()
                        .FirstOrDefault(t => typeof(IExternalCommand).IsAssignableFrom(t) && !t.IsAbstract);

                    if (type == null)
                    {
                        MessageBox.Show("未找到实现IExternalCommand的类");
                        return;
                    }

                    MethodInfo method = type.GetMethod("Execute", BindingFlags.Instance | BindingFlags.Public);
                    if (method == null)
                    {
                        MessageBox.Show("未找到Execute方法");
                        return;
                    }

                    object commandInstance = Activator.CreateInstance(type);
                    method.Invoke(commandInstance, new object[] { _commandData, _message, _elements });
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"执行错误: {ex.Message}");
            }
        }

        public string GetName() => "ScriptExecuteHandler";
    }
}
